home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 301_01 / dcuwcu.c < prev    next >
C/C++ Source or Header  |  1989-12-28  |  21KB  |  942 lines

  1. /*
  2.  * the Hollywood principle: don't call us, we'll call you
  3.  * 
  4.  * This package uses pd mouse routines and Turbo C graphics
  5.  * to implement a mouse, menu, and form handler.  An application
  6.  * program provides the following routines:
  7.  *    start(ac, av, ep)    - initialization
  8.  *    menu(m, i)        - menu m, item i was selected
  9.  *    button(b, x, y)        - unbound button was pressed 
  10.  *      keyboard(key)        - keyboard character struck
  11.  *      timer(t)                - a timer has gone off
  12.  *
  13.  * This package also provides the following interface routines:
  14.  *    finish()        - all done
  15.  *    add_menu(m, mdef)    - add a menu to the system
  16.  *      menu_state(m, on)       - turn a menu on or off
  17.  *    menu_item(m, i, str)    - change a menu item's string
  18.  *    mouse_state(on)        - turn the mouse on or off
  19.  *      mouse_shape(type, ...)    - set the mouse bitmap
  20.  *      add_timer(t, wait)    - add a timer to the system
  21.  *    form(fdef, argptr,...)    - have user fill out a form
  22.  * 
  23.  * Form definition is pretty complicated.  It's somewhat like scanf in
  24.  * that it uses a format string and %Nd or %Ns to define an input
  25.  * field.  A %[str] defines an exit button and a %(str) defines a regular
  26.  * button.  If you select an exit button, you leave the form.  A
  27.  * regular button has will toggle a value.  A '|' in the definition
  28.  * string starts a new line.
  29.  *
  30.  * If no Microsoft compatible mouse driver is installed, it works
  31.  * with keyboard input with the following conventions:
  32.  *    cursor keys control the mouse
  33.  *    F1 simulates a button 1 key depression (and release)
  34.  *    F2 will enter a menu, a second F2 leaves it
  35.  *
  36.  * Copyright Mark A. Johnson, 1989
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <graphics.h>
  41. #include <bios.h>
  42.  
  43. #define SAVE        5000    /* constant sizes            */
  44. #define MAXITEM        30
  45. #define MAXMENU        10
  46. #define MAXFORM        20
  47. #define MAXTIMER    10
  48.  
  49. #define TXT_WD        8    /* text height and width        */
  50. #define TXT_HT        8
  51.  
  52. #define TITLE    't'        /* form item types            */
  53. #define NUMBER    'd'
  54. #define STRING    's'
  55. #define EXIT    'e'
  56. #define BUTTON    'b'
  57. #define RADIO    'r'
  58.  
  59. #define ESC    27        /* constants for keyboard handling    */
  60. #define ENTER    '\r'
  61. #define TAB    '\t'
  62. #define F1    256
  63. #define F2    257
  64. #define UP    258
  65. #define DOWN    259
  66. #define LEFT    260
  67. #define RIGHT    261
  68.  
  69. #define INS_CHR    17        /* editing cursor for forms        */
  70.  
  71. #define MS_PER_TICK    64    /* milliseconds per tick (from bios)    */
  72.  
  73. typedef struct { int wid, ht; char buf[10]; } Mbits;
  74. typedef struct { char type, row, col, radio, size, *str, *data; } Form;
  75. typedef struct { char **item, size, handle, on; } Menu;
  76. typedef struct { char handle; long wait; } Timer;
  77.  
  78. static char mouse_ptr[] = { 
  79.     0xFC, 0xFC, 0xF0, 0xF8, 0xDC, 0xCE, 0x07, 0x02 
  80. };
  81. static char mouse_cross[] = {
  82.     0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18
  83. };
  84. static Mbits mbits = {
  85.     7, 7, { 0xFC, 0xFC, 0xF0, 0xF8, 0xDC, 0xCE, 0x07, 0x02, 0, 0 }
  86. };
  87. int Mx, My;            /* current mouse coordinates        */
  88. static int Mhotx=0, Mhoty=0;    /* offset for mouse cursor hotspot    */
  89. static int Mshow;        /* is mouse showing or not        */
  90. static int Mpresent;        /* is a mouse present or not        */
  91.  
  92. int Maxx, Maxy;            /* graphics driver position range    */
  93. int MaxColor;            /* graphics driver color range        */
  94.  
  95. int MaxSave;            /* keep track of max size save needed    */
  96. static char save[SAVE];        /* buffer to save patches of screen    */
  97.  
  98. static char *items[MAXITEM];    /* menu item table            */
  99. static int last_item;        /* size of menu table            */
  100. static Menu menus[MAXMENU];    /* menu descriptor table        */
  101. static int last_menu;        /* size of menu descriptor table    */
  102.  
  103. static Form forms[MAXFORM];    /* form table                */
  104. static int fcnt;        /* number of items in the form table    */
  105. static char fbuf[100];        /* buffer for the form def'tion string    */
  106. static int fwid;        /* max width of the form        */
  107. static int fht;            /* max height of the form        */
  108. static int fl, ft, fr, fb;    /* form box coordinates            */
  109. static char ebuf[100];        /* edit buffer for form item        */
  110. static int ebufx;        /* index into the edit buffer        */
  111. static int edit;        /* index of current editable item    */
  112.  
  113. static Timer timers[MAXTIMER];    /* a set of timers            */
  114. static int last_timer;        /* number of active timers        */
  115. static long last_tick;        /* last tick of the old ticker        */
  116.  
  117. main(argc, argv, envp) char **argv, **envp; {
  118.     int b, x, y;
  119.     int driver, mode;
  120.  
  121.     Mx = My = 0;
  122.     if ((Mpresent = ms_init()) == 0)
  123.         printf("no mouse!\n");
  124.  
  125.     driver = mode = DETECT; /* detect */
  126.     initgraph(&driver, &mode, ".");
  127.     if (driver < 0) {
  128.         printf("cannot open graph driver, driver=%d\n", driver);
  129.         exit(1);
  130.     }
  131.     start(argc, argv, envp);
  132.     Maxx = getmaxx();
  133.     Maxy = getmaxy();
  134.     MaxColor = getmaxcolor();
  135.     last_tick = biostime(0, 0L);
  136.     if (Mpresent)
  137.         mouse_appl();
  138.     else    key_appl();
  139. }
  140.  
  141. /* drive the application from the mouse */
  142.  
  143. static
  144. mouse_appl() {
  145.     int b, x, y;
  146.     ms_setspeed(10, 10);
  147.     ms_hbounds(0, Maxx);
  148.     ms_vbounds(0, Maxy);
  149.     mouse_state(1);
  150.     while (1) {
  151.         do_timer();
  152.         if (kbhit()) {
  153.             mouse_state(0);
  154.             keyboard(getch());
  155.             mouse_state(1);
  156.         }
  157.         if (ms_button()) {
  158.             delay(50);
  159.             if ((b = ms_button()) != 0) {
  160.                 mouse_state(0);
  161.                 if (b == 2)
  162.                     do_menu();
  163.                 else    {
  164.                     button(b, Mx, My);
  165.                     while (ms_button())
  166.                         ;
  167.                 }
  168.                 mouse_state(1);
  169.             }
  170.         }
  171.         ms_motion(&x, &y);
  172.         if (x || y) move_mouse(x, y);
  173.     }
  174. }
  175.  
  176. /* drive the application from the keyboard */
  177.  
  178. static
  179. key_appl() {
  180.     int c, x, y;
  181.     mouse_state(1);
  182.     while (1) {
  183.         do_timer();
  184.         if (kbhit()) {
  185.             c = key();
  186.             if (c == F1) {
  187.                 mouse_state(0);
  188.                 button(1, Mx, My);
  189.                 mouse_state(1);
  190.             }
  191.             else if (c == F2) {
  192.                 mouse_state(0);
  193.                 do_menu();
  194.                 mouse_state(1);
  195.             }
  196.             else if (is_arrow(c, &x, &y))
  197.                 move_mouse(x, y);
  198.             else    {
  199.                 mouse_state(0);
  200.                 keyboard(c);
  201.                 mouse_state(1);
  202.             }
  203.         }
  204.     }
  205. }
  206.  
  207. /* change the mouse bitmap */
  208.  
  209. mouse_shape(type, data, hx, hy) char *data; {
  210.     int i;
  211.     char *p;
  212.     int m_on = Mshow;
  213.     if (m_on) mouse_state(0);
  214.     switch (type) {
  215.     case 0: 
  216.         p = mouse_ptr; 
  217.         Mhotx = Mhoty = 0;
  218.         break;
  219.     case 1: 
  220.         p = mouse_cross; 
  221.         Mhotx = Mhoty = 3;
  222.         break;
  223.     case 2: 
  224.         p = data; 
  225.         Mhotx = hx;
  226.         Mhoty = hy;
  227.         break;
  228.     }
  229.     for (i = 0; i < 8; i++)
  230.         mbits.buf[i] = p[i];
  231.     if (m_on) mouse_state(1);
  232. }
  233.  
  234. /* handle keyboard input, map F1, etc to single keys */
  235.  
  236. static
  237. key() {
  238.     int c;
  239.     static int back = 0;
  240.     if (back) {
  241.         c = back;
  242.         back = 0;
  243.     }
  244.     else    {
  245.         c = getch();
  246.         if (c == 0) {
  247.             switch (c = getch()) {
  248.             case 59: c = F1; break;
  249.             case 60: c = F2; break;
  250.             case 72: c = UP; break;
  251.             case 80: c = DOWN; break;
  252.             case 77: c = RIGHT; break;
  253.             case 75: c = LEFT; break;
  254.             default: back = c; c = 0; break;
  255.             }
  256.         }
  257.     }
  258.     return c;
  259. }
  260.  
  261. /* is the given key an arrow key, if so, set the delta x,y pointers */
  262.  
  263. static
  264. is_arrow(c, xp, yp) int c, *xp, *yp; {
  265.     static int lastc, cnt;
  266.     if (c != lastc) {
  267.         lastc = c;
  268.         cnt = 1;
  269.     }
  270.     else    cnt++;
  271.     *xp = *yp = 0;
  272.     switch (c) {
  273.     case UP:
  274.         *yp = -cnt;
  275.         break;
  276.     case DOWN:
  277.         *yp = cnt;
  278.         break;
  279.     case LEFT:
  280.         *xp = -cnt;
  281.         break;
  282.     case RIGHT:
  283.         *xp = cnt;
  284.         break;
  285.     default:
  286.         return 0;
  287.     }
  288.     return 1;
  289. }
  290.  
  291. /* the application requests termination */
  292.  
  293. finish() {
  294.     closegraph();
  295.     exit(0);
  296. }
  297.  
  298. /* move the mouse a bit */
  299.  
  300. static
  301. move_mouse(dx, dy) {
  302.     mouse_state(0);
  303.     Mx += dx;
  304.     if (Mx < 0) Mx = 0;
  305.     if (Mx > Maxx) Mx = Maxx;
  306.     My += dy;
  307.     if (My < 0) My = 0;
  308.     if (My > Maxy) My = Maxy;
  309.     mouse_state(1);
  310. }
  311.  
  312. /* turn the mouse picture on or off */
  313.  
  314. mouse_state(on) {
  315.     if (on ^ Mshow)
  316.         putimage(Mx-Mhotx, My-Mhoty, &mbits, XOR_PUT);
  317.     Mshow = on;
  318. }
  319.  
  320. /* add a timer to the system, wait is in milliseconds */
  321.  
  322. add_timer(handle, wait) long wait; {
  323.     int i, j;
  324.     long total = 0L;
  325.  
  326.     /* find the insertion point */
  327.     for (i = 0; i < last_timer; i++) {
  328.         if (wait < total + timers[i].wait)
  329.             break;
  330.         total += timers[i].wait;
  331.     }
  332.  
  333.     /* shuffle things down if necessary */
  334.     if (i < last_timer) { 
  335.         for (j = last_timer; j > i; j--)
  336.             timers[j] = timers[j-1];
  337.     }
  338.     
  339.     /* insert the new timer, adjust wait to incr over previous */
  340.     wait -= total;
  341.     timers[i].handle = handle;
  342.     timers[i].wait = wait;
  343.  
  344.